﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using CSharp.Libs.Koc;
using System.Collections.ObjectModel;
using CSharp.Libs.Koc.UserControls.ItemClasses;
using CSharp.Libs.Koc.Models;
using CSharp.Libs.Koc.KernelModels;
using System.Threading;
using System.Collections;
using System.Windows.Controls;
using System.Windows;

namespace CSharp.Libs.WPF.UserControls
{
    public class KocKernel2ViewModel : ViewModelBase
    {
        #region declarations
        private Dispatcher _DISP = null;
        private Kernel _KRNL = null;

        private ObservableCollection<UserProfileItem> _ocUsers = new ObservableCollection<UserProfileItem>();

        private UserProfileItem _upiSelectedUser = null;

        private int _intServerId = 1;

        private const string DEFAULT_CONTROL_TITLE = "Kernel Control";

        #region events
        public delegate void BeforeUserChangeEventHandler(object sender, UserChangeEventArgs ucea);
        public event BeforeUserChangeEventHandler BeforeUserChange;
        private void ThrowBeforeUserChangeEvent(
            UserChangeEventArgs ucea)
        {
            if (BeforeUserChange != null)
            {
                BeforeUserChange(this, ucea);
            }
        }

        public delegate void AfterUserChangeEventHandler(object sender, UserChangeEventArgs ucea);
        public event AfterUserChangeEventHandler AfterUserChange;
        private void ThrowAfterUserChangeEvent(
            UserChangeEventArgs ucea)
        {
            if (AfterUserChange != null)
            {
                AfterUserChange(this, ucea);
            }
        }

        public delegate void BeforeServerChangeEventHandler(object sender, ServerChangeEventArgs scea);
        public event BeforeServerChangeEventHandler BeforeServerChange;
        private void ThrowBeforeServerChangeEvent(
            ServerChangeEventArgs scea)
        {
            if (BeforeServerChange != null)
            {
                BeforeServerChange(this, scea);
            }
        }

        public delegate void AfterServerChangeEventHandler(object sender, ServerChangeEventArgs scea);
        public event AfterServerChangeEventHandler AfterServerChange;
        private void ThrowAfterServerChangeEvent(
            ServerChangeEventArgs scea)
        {
            if (AfterServerChange != null)
            {
                AfterServerChange(this, scea);
            }
        }
        #endregion
        #endregion



        #region constructor / finalizer
        public KocKernel2ViewModel(
            Dispatcher DISP,
            Kernel KRNL)
        {
            _DISP = DISP;
            _KRNL = KRNL;

            _KRNL.TM.ChatReceived += new TrafficMonitor.ChatReceivedEventHandler(TM_ChatReceived);

            int.TryParse(_KRNL.LAO.GetOption(constants.LAO_DEFAULT_SERVER_ID), out _intServerId);
        }
        #endregion



        #region event handling
        void TM_ChatReceived(object sender, ChatReceivedEventArgs crea)
        {
            try
            {
                if (PhpCommandGenerator.Users.Count > _ocUsers.Count)
                {
                    _DISP.Invoke((Action)delegate
                    {
                        try
                        {
                            foreach (KeyValuePair<string, UserValidatorItem> kvpUser in PhpCommandGenerator.Users)
                            {
                                if (!_usersContainsFbUid(kvpUser.Value.FbUid))
                                {
                                    UserValidatorItem UVI = kvpUser.Value;
                                    UserProfileItem UPI = new UserProfileItem();
                                    UPI.UVI = UVI;

                                    Thread thr = new Thread((ParameterizedThreadStart)delegate
                                    {
                                        _getUserProfile(UPI);
                                    });
                                    thr.Start();

                                    _ocUsers.Add(UPI);
                                    OnPropertyChanged("Users");
                                }
                            }

                        }
                        catch (Exception ex)
                        {
                            _KRNL.EC.AddException(ex, this.ToString(), _KRNL.EC.Tools.GetCurrentMethodName());
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion



        #region private functions
        /// <summary>_usersContainsFbUid</summary>
        /// <param name="FbUid"></param>
        /// <returns></returns>
        /// <history>04.02.2012</history>
        private bool _usersContainsFbUid(
            string FbUid)
        {
            foreach (UserProfileItem UPI in _ocUsers)
            {
                if (UPI.FbUid == FbUid)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>_getUserAlliance</summary>
        /// <history>03.02.2012</history>
        /// <history>modified 09.02.2012: changed handlig of Profile Item</history>
        private void _getUserProfile(
            UserProfileItem UPI)
        {
            if (UPI != null && UPI.UVI != null && PhpCommandGenerator.IsInitialized)
            {
                //get viewCourt
                using (PhpCommand pcDispatch = PhpCommandGenerator.GetPhpCommand(_KRNL.EC, PhpCommands._dispatch, _intServerId, UPI.FbUid))
                {
                    //Check if viewCourt command was generated
                    if (pcDispatch == null)
                    {
                        return;
                    }

                    //set needed parameters
                    pcDispatch.Parameters.Add(PhpCommandParameters.USER_ID, pcDispatch.Parameters[PhpCommandParameters.TV_UID]);
                    pcDispatch.Parameters[PhpCommandParameters.CTRL] = "PlayerProfile";
                    pcDispatch.Parameters[PhpCommandParameters.ACTION] = "get";

                    //get result
                    Hashtable htUserViewCourt = null;
                    pcDispatch.GetAnswerHashtable(out htUserViewCourt);

                    if (htUserViewCourt != null)
                    {
                        //check result
                        if (_KRNL.ReturnHashtableOk(htUserViewCourt))
                        {
                            //read Data
                            Hashtable htProfile = htUserViewCourt["profile"] as Hashtable;
                            if (htProfile != null)
                            {
                                //UserProfileItem UPI = new UserProfileItem(_KRNL, htProfile, UVI);
                                UPI.AnalyzeHashtable(_KRNL, htProfile);

                                OnPropertyChanged("CurrentAlliance");
                            }
                        }
                        else//Result false
                        {
                            //TOODOO: Might need to start a timer here to be able to retry getting allianceId
                            //_KRNL.EC.AddException(new Exception("No viewCourt received... Ouch!!! Need a retry timer here."), this.ToString(), "_getUserAlliance()");

                            //Or just refresh UI since a user is not on every server. :D
                            if (_upiSelectedUser != null)
                            {
                                _upiSelectedUser.allianceId = "";
                                _upiSelectedUser.allianceName = "";
                                
                            }
                        }
                    }

                    //notify UI
                    _UiRefresh();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  03.07.2012</history>
        private void _UiRefresh()
        {
            _DISP.Invoke((Action)delegate
            {
                //notify UI
                OnPropertyChanged("SelectedUser");
                OnPropertyChanged("CurrentAlliance");
                OnPropertyChanged("Users");
                OnPropertyChanged("UserIsValid");
                OnPropertyChanged("UserValidText");
                OnPropertyChanged("UserIsInvalid");
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <history>created  04.07.2012</history>
        private void _UsersRefresh()
        {
            //create temp array
            ArrayList aryTemp = new ArrayList();

            //save existing upi's to temp
            foreach (UserProfileItem UPI in _ocUsers)
            {
                aryTemp.Add(UPI);
            }

            //get current server data to temp array
            foreach (UserProfileItem UPI in aryTemp)
            {
                UPI.Clear();
                _getUserProfile(UPI);
            }

            //clear users list
            _DISP.Invoke((Action)delegate
            {
                _ocUsers.Clear();
                //});

                foreach (UserProfileItem UPI in aryTemp)
                {
                    //_DISP.Invoke((Action)delegate
                    //{
                    _ocUsers.Add(UPI);
                    //});
                }
            });

            _UiRefresh();
        }
        #endregion



        #region interface
        #region properties
        public bool UserIsValid
        {
            get
            {
                if (_upiSelectedUser != null)
                {
                    return _upiSelectedUser.UserIsValid;
                }

                return false;
            }
        }

        public Visibility UserIsInvalid
        {
            get
            {
                if (_upiSelectedUser != null)
                {
                    if (_upiSelectedUser.UserIsValid)
                    {
                        return Visibility.Hidden;
                    }
                    else
                    {
                        return Visibility.Visible;
                    }
                }
                else
                {
                    return Visibility.Hidden;
                }
            }
        }

        public string UserValidText
        {
            get
            {
                if (_upiSelectedUser != null &&
                    _upiSelectedUser.FbUid.Trim() != "" &&
                    !_upiSelectedUser.UserIsValid)
                {
                    return "This FBUid is not allowed. Contact author for permission";
                }

                return DEFAULT_CONTROL_TITLE;
            }
        }

        public ObservableCollection<UserProfileItem> Users
        {
            get
            {
                return _ocUsers;
            }
        }

        public UserProfileItem SelectedUser
        {
            get
            {
                return _upiSelectedUser;
            }
            set
            {
                //break if no value
                if (value == null) { return; }

                //Create an empty instance to avoid errors
                if (_upiSelectedUser == null) { _upiSelectedUser = new UserProfileItem(); }

                //Clear reports if UserID changed
                if (_upiSelectedUser.FbUid != value.FbUid)
                {
                    //create EventArgs
                    UserChangeEventArgs UCEA = new UserChangeEventArgs(_upiSelectedUser.GetCopy(), value);

                    #region before user change
                    //throw before-event
                    ThrowBeforeUserChangeEvent(UCEA);
                    #endregion

                    //set new value
                    _upiSelectedUser = value;

                    //get user alliance info
                    Thread thr = new Thread((ParameterizedThreadStart)delegate
                    {
                        _getUserProfile(_upiSelectedUser);
                    });
                    thr.Start();

                    #region after user change
                    //throw after-event
                    ThrowAfterUserChangeEvent(UCEA);
                    #endregion
                }
            }
        }

        public string CurrentAlliance
        {
            get
            {
                if (_upiSelectedUser != null)
                {
                    return _upiSelectedUser.allianceName;
                }

                return "";
            }
        }

        public int ServerId
        {
            get
            {
                return _intServerId;
            }
            set
            {
                if (value != _intServerId &&
                    value <= constants.MAX_SERVER_NUMBER)
                {
                    //create EventArgs
                    ServerChangeEventArgs SCEA = new ServerChangeEventArgs(_intServerId, value);

                    #region before server change
                    //throw before-event
                    ThrowBeforeServerChangeEvent(SCEA);
                    #endregion

                    //set and save server id
                    _intServerId = value;
                    _KRNL.LAO.SetOption(constants.LAO_DEFAULT_SERVER_ID, _intServerId.ToString());

                    //Refresh Userslist
                    Thread thrUsersList = new Thread((ParameterizedThreadStart)delegate
                    {
                        _UsersRefresh();
                    });
                    thrUsersList.Start();

                    //get new user profile info 
                    if (_upiSelectedUser != null && _upiSelectedUser.userId != "")
                    {
                        Thread thrSelectedUser = new Thread((ParameterizedThreadStart)delegate
                        {
                            _getUserProfile(_upiSelectedUser);
                        });
                        thrSelectedUser.Start();
                    }

                    #region after server change
                    //throw after-event
                    ThrowAfterServerChangeEvent(SCEA);
                    #endregion
                }
            }
        }

        public bool SaveSeedToDisk { get { return _KRNL.SC.SaveSeedToDisk; } set { _KRNL.SC.SaveSeedToDisk = value; } }
        #endregion

        #region methods
        #endregion
        #endregion
    }
}
